/** 
 * Copyright(c) 2010 ICT,   
 * All Rights Reserved.
 * 
 * This file contains some frequently-used algorithm, especially the ones
 * deals with string.
 * Filename: fs_algo.h
 *  
 * @author			Linfeng Song
 * @last modified	2012-07-18 
 */

#pragma once

#include "stl_includes.h"

class fs_algo
{
public:
	/** 
	 * 
	 */
	static bool is_digit(char ch)
	{
		return '0' <= ch && ch <= '9';
	}
	/** 
	 * 
	 */
	static bool is_upper(char ch)
	{
		return 'A' <= ch && ch <= 'Z';
	}
	/** 
	 * 
	 */
	static bool is_lower(char ch)
	{
		return 'a' <= ch && ch <= 'z';
	}
	/** 
	 * 
	 */
	static string to_lower(const string& str)
	{
		string str_tmp = str;
		for(int i=0;i<(int)str_tmp.size();i++)
			if(fs_algo::is_upper(str_tmp[i]))
				str_tmp[i] += 32;
		return str_tmp;
	}
	/** 
	 * 
	 */
	static string to_upper(const string& str)
	{
		string str_tmp = str;
		for(int i=0;i<(int)str_tmp.size();i++)
			if(fs_algo::is_upper(str_tmp[i]))
				str_tmp[i] -= 32;
		return str_tmp;
	}
/////////////////////////////////////////////////////////
	/** 
	 * counts the number of words in a phrase
	 * @param	  str: [in]the target phrase
	 * @return	  the number of words
	 */
	static int width(const string& str)
	{
		istringstream iss(str);
		string word;
		int count = 0;
		while(iss >> word) count++;
		return count;
	}

	/** 
	 * return the first N words in a phrase
	 * @param	  phr: [in]the target phrase
	 * @param	  n: [in]represents the N
	 * @return	  the first N words
	 */
	static string get_first_n_words(const string &phr, int n)
	{
		string word = "",w = "";
		istrstream istr(phr.c_str());
		int i = 0;
		while(istr >> word)
		{
			i++;
			w += word;
			if(i < n) w += " ";
			else break;
		}

		if(i < n) w.resize(w.size()-1);
		return w;
	}

	/** 
	 * return the last N words in a phrase
	 * @param	  phr: [in]the target phrase
	 * @param	  n: [in]represents the N
	 * @return	  the last N words
	 */
	static string get_last_n_words(const string &phr, int n)
	{
		string word;
		vector<string> all;
		istrstream istr(phr.c_str());
		while(istr >> word)
		{
			all.push_back(word);
		}

		int size = int(all.size());
		if(size <= n) return phr;
		else
		{
			int i;
			string w;
			for(i = size - n; i < size; i++)
			{
				w += all[i];
				if(i < size - 1) w += " ";
			}
			return w;
		}
	}


	/** 
	 * return the word sequence array of a given phrase
	 * @param	  str: [in]the target phrase
	 * @param	  seq: [out]the result word sequence array
	 */
	static void get_word_sequence(const string& str, vector<string>& seq)
	{
		seq.clear();

		string word;
		istringstream iss(str);
		while(iss >> word) seq.push_back(word);
	}


	/** 
	 * strip all these characters in the left and right bound of current string
	 * these characters include : ' ','\t','\n' 
	 * @param	  s: [in]the target string
	 * @return	  the result string
	 */
	static string strip(const string& s)
	{
		const string chs = " \t\n";

		if (s.empty())
			return s;

		int i = 0;
		while (i < (int)s.size() && chs.find(s[i]) != string::npos)
			++i;
		int j = (int)s.size() - 1;
		while (j >= 0 && chs.find(s[j]) != string::npos)
			--j;
		++j;
		return i >= j ? "" : s.substr(i, j - i);
	}


	/** 
	 * split the target string by space char into string sequence
	 * @param	  src: [in]the target string
	 * @return	  the result string sequence
	 */
	static vector<string> split(const string& src)
	{
		istringstream iss(src);
		vector<string> r;
		string w;
		while (iss >> w)
			r.push_back(w);
		return r;
	}

	/** 
	 * split the target string by specific char into string sequence
	 * @param	  src: [in]the target string
	 * @param	  delimit: [in]the specific char
	 * @return	  the result string sequence
	 */
	static vector<string> split(const string& src, string delimit)
	{
		vector<string> r;
		int f = 0;
		int p = -1;

		while ((p = (int)src.find(delimit, p + 1)) != (int)string::npos)
		{
			if (p > f)
				r.push_back(src.substr(f, p - f));				
			f = p + (int)delimit.size();
		}
		p = (int)src.size();
		if (p > f)
			r.push_back(src.substr(f, p - f));				
		return r;
	}
 
	/** 
	 * check if a given string str satisfies starting with a specific string
	 * @param	  src: [in]the target string
	 * @param	  prefix: [in]the specific string
	 * @return    true: satisfy
	 *            false: not satisfy
	 */
	static bool startswith(const string &str, string prefix)
	{
		return prefix.size() <= str.size() && strncmp(str.c_str(), prefix.c_str(), prefix.size()) == 0;
	}

	/** 
	 * check if a given string str satisfies ending with a specific string
	 * @param	  src: [in]the target string
	 * @param	  postfix: [in]the specific string
	 * @return    true: satisfy
	 *            false: not satisfy
	 */
	static bool endswith(const string& str, string postfix)
	{
		return postfix.size() <= str.size() && strcmp(str.c_str() + (str.size() - postfix.size()), postfix.c_str()) == 0;
	}

	
	static double to_double(const char* s)
	{
		return atof(s);
	}

	
	static double to_double(const string& s)
	{
		return to_double(s.c_str());
	}
};
